﻿using AutoMapper;
using B.S.BaseData.Domain.Entities;
using B.S.BaseData.ErrorCode;
using B.S.BaseData.Infrastructure.Interfaces;
using B.S.BaseData.Read.API.Command.LeaveCommand;
using B.S.BaseData.Read.API.DTO;
using MediatR;

namespace B.S.BaseData.Read.API.CommandHandler.LeaveHandler
{
    public class QueryLeaveHandler : IRequestHandler<QueryLeaveCommand, APIPaging<LeaveDTO>>
    {
        private readonly IBaseRepository<Leave> _leaveRep;
        private readonly IMapper _mapper;
        private readonly IBaseRepository<User> _userRep;

        public QueryLeaveHandler(
            IBaseRepository<Leave> leaveRep,
            IMapper mapper,
            IBaseRepository<User> userRep)
        {
            _leaveRep = leaveRep;
            _mapper = mapper;
            _userRep = userRep;
        }

        public Task<APIPaging<LeaveDTO>> Handle(QueryLeaveCommand request, CancellationToken cancellationToken)
        {
            var result = new APIPaging<LeaveDTO>
            {
                Code = APIEnum.Success,
                Msg = "查询成功"
            };

            // 根据用户角色构建基础查询
            var baseQuery = BuildBaseQuery(request);

            // 应用过滤条件
            var filteredQuery = ApplyFilters(baseQuery, request);

            // 处理分页并返回结果
            ProcessPaging(filteredQuery, request, result);

            return Task.FromResult(result);
        }

        /// <summary>
        /// 构建基础查询（根据用户权限）
        /// </summary>
        private IQueryable<Leave> BuildBaseQuery(QueryLeaveCommand request)
        {
            // 1. 优先检查总负责人
            if (IsGeneralManager(request.UserId))
                return _leaveRep.GetAll().Where(x=>!x.IsDeleted);

            // 2. 检查部门领导
            if (IsDepartmentLeader(request.UserId, request.DepartmentId))
                return _leaveRep.GetAll().Where(x => x.DepartmentId == request.DepartmentId&&!x.IsDeleted);

            // 3. 默认查询自己的请假记录
            return _leaveRep.GetAll().Where(x => x.LeaveId == request.UserId && !x.IsDeleted);
        }

        /// <summary>
        /// 应用统一过滤条件
        /// </summary>
        private IQueryable<Leave> ApplyFilters(IQueryable<Leave> query, QueryLeaveCommand request)
        {
            // 请假名称筛选
            if (!string.IsNullOrEmpty(request.LeaveName))
                query = query.Where(x => x.LeaveName.Contains(request.LeaveName));

            // 开始时间筛选（安全解析）
            if (!string.IsNullOrEmpty(request.LeaveStartTime)
                && DateTime.TryParse(request.LeaveStartTime, out var startTime))
                query = query.Where(x => x.LeaveStartTime >= startTime);

            // 结束时间筛选（安全解析）
            if (!string.IsNullOrEmpty(request.LeaveEndTime)
                && DateTime.TryParse(request.LeaveEndTime, out var endTime))
                query = query.Where(x => x.LeaveEndTime < endTime.AddDays(1));

            // 审批状态筛选
            if (request.ApprovalStatus > 0)
                query = query.Where(x => x.ApprovalStatus == request.ApprovalStatus);

            return query;
        }

        /// <summary>
        /// 处理分页逻辑
        /// </summary>
        private void ProcessPaging(IQueryable<Leave> query,
            QueryLeaveCommand request,
            APIPaging<LeaveDTO> result)
        {
            // 计算总数和页数
            result.TotalCount = query.Count();
            result.PageCount = (int)Math.Ceiling(result.TotalCount / (double)request.PageSize);

            // 应用分页
            var pagedQuery = query
                .OrderByDescending(x => x.Id)
                .Skip((request.PageIndex - 1) * request.PageSize)
                .Take(request.PageSize);

            // 映射结果
            result.Items = _mapper.Map<List<LeaveDTO>>(pagedQuery);
        }

        /// <summary>
        /// 检查是否是总负责人
        /// </summary>
        private bool IsGeneralManager(int userId) =>
            _userRep.GetAll()
                .Any(x => x.UserId == userId && x.PowerId == (int)PowerId.总负责人);

        /// <summary>
        /// 检查是否是部门领导
        /// </summary>
        private bool IsDepartmentLeader(int userId, int departmentId) =>
            _userRep.GetAll()
                .Any(x => x.UserId == userId
                       && x.DepartmentId == departmentId
                       && x.PowerId == (int)PowerId.部门领导人);
    }
}